import logging

from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from page_object.driver.AndroidClient import AndroidClient
import yaml


class BasePage(object):
    '''
    driver可以替换成不同的平台，比如小程序，ios， webview
    其他的页面都继承 BasePage，AndroidClient.driver写成 self.driver 也方便些
    '''
    # 清理已有 handlers
    root_logger = logging.getLogger()
    for h in root_logger.handlers[:]:
        root_logger.removeHandler(h)
    logging.basicConfig(level=logging.INFO)

    def __init__(self):
        self.driver = AndroidClient.driver

    @classmethod
    def getDriver(cls):
        cls.driver = AndroidClient.driver
        return cls.driver
    @classmethod
    def getClient(cls):
        return AndroidClient

    i = 1
    def find(self, kv) -> WebElement:
        '''
        封装find方法，之后只需要调用find方法就好，如果有弹窗之类的东西，最好使用find方法，这个方法可以自动处理弹窗

        :param kv:
        :return:
        '''
        try:
            r = self.driver.find_elements_by_id(*kv)
            if r > 0:
                return self.driver.find_element(*kv)
        except:
            self.handle_alert()
            self.i += 1
            logging.info(self.i)
            # 递归处理
            if self.i < 3:
                return self.find(kv)
            else:
                return self.driver.find_element(*kv)
        return self.driver.find_element(*kv)

    def handle_alert(self):
        '''
        弹窗黑名单，弹窗处理逻辑，在数组里面添加元素的resource-id
        :reurn:
        '''
        aler_box = []
        aler_box.append('confirm_tv')
        aler_box.append('app_activity_close_iv')
        aler_box.append('tvCancle')

        # 获取页面xml，需要获取两次，y是正确的xml
        x = str(self.driver.page_source)
        y = str(self.driver.page_source)

        for i in range(0, len(aler_box)):
            if aler_box[i] in y:
                self.driver.find_element_by_id(aler_box[i]).click()

        #
        # for i in range(0, len(aler_box)):
        #     result = self.driver.find_elements_by_id(aler_box[i])  #find_elements方法，如果找到了就返回对象，找不到就返回空
        #     if len(result) > 0:
        #         self.driver.find_element_by_id(aler_box[i]).click()

    def find_by_xpath(self, text) ->WebElement:
        """
        封装xpath方法，就不用写xpath了
        :param text: 定位参数
        :return:
        """
        return self.find((By.XPATH, "//*[@text='%s']" %text))

    def find_contain_by_xpath(self, text) ->WebElement:
        """
        封装包含的xpath方法
        """
        return self.find((By.XPATH, "//*[contains(@text, '%s')]" %text))

    def swipe_to_element_by_text(self, num, text):
        '''
        封装根据文本，滑动定位到某一元素方法,
        很牛逼的方法，你翻遍郑州市都不一定能找到人会，

        :param num: 第几个滑动控件，一般传0就可以
        :param text: 需要定位的文本
        :return:
        '''
        # 本来的使用方法
        # self.driver.find_element_by_android_uiautomator(
        # 'new UiScrollable(new UiSelector().scrollable(true).instance(1)).scrollIntoView(new UiSelector().text("打招呼").instance(0));'
        # )
        return self.driver.find_element_by_android_uiautomator(
        'new UiScrollable(new UiSelector().scrollable(true).instance(%d)).scrollIntoView(new UiSelector().text("%s").instance(0));' % (num, text)
        )
    def swipe_to_element_by_resource_id(self, num, id):
        '''
        封装根据id滑动定位到某一元素方法, id需要传全部的resource-id
        很牛逼的方法，你翻遍郑州市都不一定能找到人会，

        :param num: 第几个滑动控件，一般传0就可以
        :param id: 需要定位的id 传全部的resource-id
        :return:
        '''
        return self.driver.find_element_by_android_uiautomator(
        'new UiScrollable(new UiSelector().scrollable(true).instance(%d)).scrollIntoView(new UiSelector().resourceId("%s").instance(0));' % (num, id)
        )

    def loadSteps(self, po_path, key, **kwargs):
        # open()方法读取方式需要改为'rb',原来是'r'只读
        file = open(po_path, 'rb')
        po_data = yaml.load(file, Loader=yaml.FullLoader)
        po_method = po_data[key]
        for step in po_method:
            element = self.driver.find_element(by=step['by'], value=step['locator'])
            actions = str(step['action']).lower()

            #todo: 定位失败，多数是弹框，try catch后进入一个弹窗处理逻辑
            if actions == 'click':
                element.click()
            elif actions == 'sendkeys':
                text = str(step['text'])
                #不懂
                for k, v in kwargs.items():
                    text = text.replace("$%s" %k, v)
                element.send_keys(text)
            else:
                print('game over')
    #
    # @classmethod
    # def byAttribute(self, text=None, id=None):
    #     text_selector = ""
    #
    #     if (text != None):
    #         text_selector = "@text='" + text + "'"
    #     if (id != None):
    #         id_selector = "contains(@resource-id, '" + id + "')"
    #         # return 'new UiSelector().resourceId("' + id + '").text("' + text + '")'
    #         return "//*[" + text_selector + " and " + id_selector + "]"
    #     else:
    #         # return 'new UiSelector().text("'+text+'")'
    #         return "//*[" + text_selector + "]"
    #
    # def exception_handle(self):
    #     self.black_words = [self.byAttribute(text="好的"), self.byAttribute(text="下次再说")]
    #
    #     for w in self.black_words:
    #         elements = Appium.getDriver().find_elements(By.XPATH, w)
    #         if len(elements) > 0:
    #             elements[0].click()
    #             return Appium.getDriver().find_element(By.XPATH, w)
    #
    # def exception_handle2(self):
    #     self.black_words = [self.byAttribute(text="好的"), self.byAttribute(text="下次再说")]
    #
    #     # todo: 优化弹框处理逻辑，发现toast，自动发现兼容性问题等。。。
    #     page_source = Appium.getDriver().page_source
    #     print(page_source)
    #     # parser = etree.XMLParser(encoding='utf-8')
    #     xml = etree.XML(str(page_source).encode("utf-8"))
    #     for w in self.black_words:
    #         print(w)
    #         if (len(xml.xpath(w)) > 0):
    #             Appium.getDriver().find_element(By.XPATH, w).click()




























